package net.shambolica.jport.test;

import static net.erl.objects.ET.atom;
import static net.erl.objects.ET.tuple;
import net.erl.objects.ErlNumber;
import net.erl.objects.ErlTerm;
import static net.erl.objects.pattern.EP.pis_number;
import static net.erl.objects.pattern.EP.ptuple;
import static net.erl.objects.pattern.EP.pvar;
import net.shambolica.jport.runner.DataConnection;
import net.shambolica.jport.runner.JPortSimpleRunner;
import net.shambolica.jport.runner.JPortNetRunner;
import org.slf4j.LoggerFactory;
import org.apache.log4j.Level;

import java.io.IOException;
import java.util.Map;

/**
 * A JPort that ping-pongs with the Erlang Master.
 * <br/>Loop:
 * <br/>- Wait for {ping, Value} or {exit, Code}.
 * <br/>- If was {ping,...} -> Send {pong, Value}, go back to waiting.
 * <br/>- Else exit with Code as the exit status (must be integer).
 */
public class PingPongTestMain extends JPortSimpleRunner {

    public PingPongTestMain() {
        super(LoggerFactory.getLogger(PingPongTestMain.class));
    }

    protected int run(DataConnection io) throws IOException, InterruptedException {

        while (true) {
            log.info("waiting...");
            ErlTerm input = io.readTerm();
            if (input == null) {
                log.info("no input, exiting with connection error");
                return JPortNetRunner.STATUS_CONNECTION_ERROR;
            }
            Map<String,ErlTerm> match;
            if ((match = ptuple(atom("ping"),pvar("Value")).match(input)) != null) {
                log.info("got ping (value={})", match.get("Value"));
                ErlTerm output = tuple(atom("pong"),match.get("Value"));
                log.info("sending {}", output);
                io.writeTerm(output);
            } else if ((match = ptuple(atom("exit"), pvar("Code", pis_number())).match(input)) != null) {
                log.info("got exit with code {}", match.get("Code"));
                int exitStatus = ((ErlNumber)match.get("Code")).getIntValue();
                log.info("got integer exit status {}", exitStatus);
                return exitStatus;
            } else {
                log.info("got unexpected term: {}", input);
                log.info("returning to sender");
                io.writeTerm(tuple(atom("unexpected"),input));
            }
        }

    }


    public static void main(String[] args) throws IOException {

        initLog("ping_pong_test.log", null, null/*Level.INFO*/);
        int exitStatus = new PingPongTestMain().run();
        System.exit(exitStatus);
        
    }


}
